package com.changzhi.service.impl;

import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.changzhi.common.constans.Constants;
import com.changzhi.common.constans.RedisConstans;
import com.changzhi.common.enums.GiftBackgroundEnum;
import com.changzhi.common.exception.ServiceException;
import com.changzhi.common.util.DateUtil;
import com.changzhi.common.util.Result;
import com.changzhi.common.util.SignUtils;
import com.changzhi.ldyl.model.*;
import com.changzhi.ldyl.model.dto.LoveDto;
import com.changzhi.ldyl.model.vo.LoveVo;
import com.changzhi.mapper.*;
import com.changzhi.service.ActivityService;
import com.changzhi.service.LoveService;
import com.changzhi.service.UserService;
import com.changzhi.util.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;

/**
 * @Description:
 * @author: 小落
 * @date: 2020年11月02日
 */
@Slf4j
@Service
public class LoveServiceImpl extends ServiceImpl<ActivityMapper, Activity> implements LoveService {

	@Resource
	private ActivityService activityService;
	@Resource
	private ActivityRecordMapper activityRecordMapper;
	@Resource
	private SysDictMapper sysDictMapper;
	@Resource
	private UserDressUpMapper userDressUpMapper;
	@Resource
	private UserAccountBookMapper userAccountBookMapper;
	@Autowired
	private RedisUtil redisUtil;
	@Autowired
	private UserService userService;
	@Value("${host}")
	private String host;

/*	@PostConstruct
	public void init(){
		//查活动
		redisUtil.del(RedisConstans.ACTIVITY + 2);
		Activity activity = activityService.getActivity(2);
		List<Integer> giftIdList = JSON.parseArray(activity.getProperty2(), Integer.class);
		int i = 0;
		//初始化活动时间和活动礼物id及活动数据到缓存中
		Map<String,Object> map = new HashMap<>();
		for (GiftBackgroundEnum anEnum : GiftBackgroundEnum.values()) {
			//初始化枚举
			anEnum.setGiftConfigId(giftIdList.get(i));
			i ++;
		}
		map.put("giftIdList", giftIdList);
		map.put("startTime", activity.getStartTime().toInstant(ZoneOffset.of("+8")).toEpochMilli());
		map.put("endTime", activity.getEndTime().toInstant(ZoneOffset.of("+8")).toEpochMilli());
		redisUtil.set(RedisConstans.ACTIVITY_LOVE, map, RedisConstans.ONE_MONTH);
	}*/

	@Override
	public List<LoveVo> getConfessionWallList(LoveDto loveDto) {
		List<LoveVo> loveList = redisUtil.get(RedisConstans.ACTIVITY_LOVE_WALL);
		if(CollectionUtils.isEmpty(loveList)){
			loveList = activityRecordMapper.getLoveList();
			for (LoveVo loveVo : loveList) {
				loveVo.setBackground(GiftBackgroundEnum.getBackground(loveVo.getGiftId()));
				if(StringUtils.isBlank(loveVo.getAvatarUrl())){
					loveVo.setAvatarUrl(Constants.DEFAULT_AVATAR);
				}
				if(StringUtils.isBlank(loveVo.getTargetAvatarUrl())){
					loveVo.setTargetAvatarUrl(Constants.DEFAULT_AVATAR);
				}
				loveVo.setCreateTimeStr(
						DateUtil.showTime(loveVo.getCreateTime(), null));
			}
			redisUtil.set(RedisConstans.ACTIVITY_LOVE_WALL, loveList, RedisConstans.ONE_HOUR);
		} else {
			for (LoveVo loveVo : loveList) {
				loveVo.setCreateTimeStr(DateUtil.showTime(loveVo.getCreateTime(), null));
			}
		}
		return loveList;
	}

	@Override
	public List<LoveVo> getConfessionUserList(LoveDto loveDto) {
		if(StringUtils.isBlank(loveDto.getUserId())){
			throw new ServiceException("用户id不能为空");
		}
		List<LoveVo> resultList = new ArrayList<>();
		List<Map<String,Object>> mapList = redisUtil.hGetValuesList(RedisConstans.ACTIVITY_GIFT_USER + loveDto.getUserId());
		if(CollectionUtils.isEmpty(mapList)){
			return resultList;
		}
		Iterator<Map<String, Object>> iterator = mapList.iterator();
		while (iterator.hasNext()){
			Map<String, Object> next = iterator.next();
			if(next.get("status") != null){
				iterator.remove();
			}
		}
		//根据目标id进行分组
		Map<String, List<Map<String, Object>>> groupList = mapList.stream().collect(groupingBy(map -> map.get("targetUserId").toString()));
		for (String targetUserId : groupList.keySet()) {
			User targetUser = userService.getUser(targetUserId);
			if(targetUser == null){
				continue;
			}
			LoveVo loveVo = new LoveVo();
			loveVo.setTargetUserId(targetUser.getUserId());
			loveVo.setTargetNickname(targetUser.getNickname());

			List<Map<String, Object>> list = groupList.get(targetUserId);
			loveVo.setCount(list.size());
			if(list.size() > 1){
				//取礼物值最大的那个
				list.sort((Map<String, Object> s1, Map<String, Object> s2) -> (Integer) s2.get("loveNum") - (Integer) s1.get("loveNum"));
			}
			loveVo.setGiftId((Integer) list.get(0).get("giftConfigId"));
			resultList.add(loveVo);
		}
		return resultList;
	}

	@Override
	public void confession(LoveDto loveDto) {
		//验参
		if(StringUtils.isBlank(loveDto.getUserId())){
			throw new ServiceException("用户id不能为空");
		}
		if(StringUtils.isBlank(loveDto.getTargetUserId())){
			throw new ServiceException("目标id不能为空");
		}
		if(loveDto.getGiftId() == null){
			throw new ServiceException("礼物id不能为空");
		}
		if(StringUtils.isBlank(loveDto.getContent())){
			throw new ServiceException("告白内容不能为空");
		}
		if(loveDto.getContent().length() > 20){
			throw new ServiceException("告白墙告白内容仅限20个字内");
		}
		//敏感词验证
		if(checkSensitive(loveDto.getContent())){
			throw new ServiceException("内容包含敏感词，请重新填写");
		}
		//查询剩余次数
		List<Map<String,Object>> mapList = redisUtil.hGetValuesList(RedisConstans.ACTIVITY_GIFT_USER + loveDto.getUserId());
		if(CollectionUtils.isEmpty(mapList)){
			throw new ServiceException("告白次数不足");
		}
		Map<String, List<Map<String, Object>>> groupList = mapList.stream().collect(groupingBy(map -> map.get("targetUserId").toString()));
		List<Map<String, Object>> list = groupList.get(loveDto.getTargetUserId());
		if(CollectionUtils.isEmpty(list)){
			throw new ServiceException("告白次数不足");
		}
		boolean flag = false;
		Map<String, Object> redisMap = new HashMap<>();
		for (Map<String, Object> map : list) {
			if(map.get("giftConfigId").equals(loveDto.getGiftId()) && map.get("status") == null){
				flag = true;
				//设为已领取
				redisMap = map;
				redisMap.put("status", 1);
				break;
			}
		}
		if(!flag){
			throw new ServiceException("告白次数不足");
		}
		//告白
		ActivityRecord record = new ActivityRecord();
		record.setActivityId(2);
		record.setUserId(loveDto.getUserId());
		record.setTargetUserId(loveDto.getTargetUserId());
		record.setGiftId(loveDto.getGiftId());
		record.setContent(loveDto.getContent());
		record.setValue((Integer) redisMap.get("loveNum"));
		record.setGroupId(CommonUtil.getGroupId(loveDto.getUserId(),loveDto.getTargetUserId()));
		activityRecordMapper.insert(record);
		//减少告白次数
		redisUtil.hset(RedisConstans.ACTIVITY_GIFT_USER + loveDto.getUserId(), String.valueOf(redisMap.get("giftId")), redisMap);
		//删除缓存
		redisUtil.del(RedisConstans.ACTIVITY_LOVE_WALL);
	}

	private void refresh(){
		Long giftUserId = redisUtil.get(RedisConstans.ACTIVITY_GIFT_UPDATE);
		if(giftUserId != null){
			//有数据更新，删除缓存
			redisUtil.del(RedisConstans.ACTIVITY_GIFT_UPDATE);
			redisUtil.del(RedisConstans.ACTIVITY_LOVE_RANKING);
			redisUtil.del(RedisConstans.ACTIVITY_LOVE_REWARD);
		}
	}

	@Override
	public List<LoveVo> getRankingList(LoveDto loveDto) {
		refresh();
		List<LoveVo> rankingList = redisUtil.get(RedisConstans.ACTIVITY_LOVE_RANKING);
		if(CollectionUtils.isEmpty(rankingList)){
			long start = System.currentTimeMillis();
			Activity activity = activityService.getActivity(2);
			List<Integer> giftIdList = JSON.parseArray(activity.getProperty2(), Integer.class);
			rankingList = activityRecordMapper.getRankingList(activity.getStartTime(), activity.getEndTime(), giftIdList);
			for (LoveVo loveVo : rankingList) {
				if(StringUtils.isBlank(loveVo.getAvatarUrl())){
					loveVo.setAvatarUrl(Constants.DEFAULT_AVATAR);
				}
				if(StringUtils.isBlank(loveVo.getTargetAvatarUrl())){
					loveVo.setTargetAvatarUrl(Constants.DEFAULT_AVATAR);
				}
				loveVo.setGroupId(CommonUtil.getGroupId(loveVo.getUserId(), loveVo.getTargetUserId()));
			}
			Map<String, List<LoveVo>> groupList = rankingList.stream().collect(Collectors.groupingBy(LoveVo::getGroupId));
			//重置返回list
			rankingList = new ArrayList<>();
			for (Map.Entry<String, List<LoveVo>> entry : groupList.entrySet()) {
				List<LoveVo> subList = entry.getValue();
				if(subList.size() == 1){
					rankingList.addAll(subList);
				} else if (subList. size() > 1){
					LoveVo subVo = new LoveVo();
					BeanUtils.copyProperties(subList.get(0), subVo);
					subVo.setValue(0);
					for (LoveVo loveVo : subList) {
						subVo.setValue(subVo.getValue() + loveVo.getValue());
					}
					rankingList.add(subVo);
				}
			}
			rankingList.sort(Comparator.comparing(LoveVo::getValue, Comparator.reverseOrder()));
			if(rankingList.size() > 50){
				rankingList = rankingList.subList(0, 50);
			}
			redisUtil.set(RedisConstans.ACTIVITY_LOVE_RANKING, rankingList, RedisConstans.ONE_HOUR);
			log.info("methodName:getRankingList,耗时={}", System.currentTimeMillis() - start);
		}
		return rankingList;
	}

	@Override
	public LoveVo getRewardInfo(LoveDto loveDto) {
		if(StringUtils.isBlank(loveDto.getUserId())){
			throw new ServiceException("用户id不能为空");
		}
		LoveVo cache = (LoveVo) redisUtil.hget(RedisConstans.ACTIVITY_LOVE_REWARD , loveDto.getUserId());
		if(cache != null){
			return cache;
		}
		//查数据库
		Activity activity = activityService.getActivity(2);
		List<Integer> giftIdList = JSON.parseArray(activity.getProperty2(), Integer.class);
		Long sumValue = activityRecordMapper.getUserLoveNum(loveDto.getUserId(), activity.getStartTime(), activity.getEndTime(), giftIdList);
		Long targetSumValue = activityRecordMapper.getTargetLoveNum(loveDto.getUserId(), activity.getStartTime(), activity.getEndTime(), giftIdList);
		List<Map<String, Object>> giftList = new ArrayList<>();
		JSONArray array = JSON.parseArray(activity.getProperty1());
		for (int i = 0; i < array.size(); i++) {
			//状态：0=未达到领取条件，1=待领取，2=已领取
			Map<String, Object> map = JSON.parseObject(array.getString(i), Map.class);
			JSONArray jsonArray = (JSONArray) map.get("gifts");
			for (int j = 0; j < jsonArray.size(); j++) {
				if(isReceiveRecord(loveDto.getUserId(), jsonArray.getJSONObject(j).getInteger("giftId"))){
					jsonArray.getJSONObject(j).put("status", 2);
				} else if(j == 0 ? jsonArray.getJSONObject(j).getInteger("targetValue") <= sumValue : jsonArray.getJSONObject(j).getInteger("targetValue") <= targetSumValue){
					jsonArray.getJSONObject(j).put("status", 1);
				} else {
					jsonArray.getJSONObject(j).put("status", 0);
				}
			}
			giftList.add(map);
		}
		LoveVo result = new LoveVo();
		result.setGiftList(giftList);
		redisUtil.hset(RedisConstans.ACTIVITY_LOVE_REWARD, loveDto.getUserId(), result, RedisConstans.ONE_HOUR);
		return result;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Map<String,Object> receiveGift(LoveDto loveDto) {
		//检验
		String userId = loveDto.getUserId();
		Integer giftId = loveDto.getGiftId();
		if(StringUtils.isBlank(userId)){
			throw new ServiceException("用户id不能为空");
		}
		if(giftId == null){
			throw new ServiceException("礼物id不能为空");
		}
		Activity activity = activityService.getActivity(2);
		List<Integer> giftIdList = JSON.parseArray(activity.getProperty2(), Integer.class);
		//获取装扮数据
		SysDict sysDict = sysDictMapper.selectById(giftId);
		if (sysDict == null) {
			throw new ServiceException("获取装扮信息失败");
		}
		//是否已领取
		if(isReceiveRecord(userId,  giftId)){
			throw new ServiceException("请勿重复领取");
		}
		//查询活动期间内当前礼物总值
		//int sumValue = getSumValue(userId);
		Long sumValue = activityRecordMapper.getUserLoveNum(loveDto.getUserId(), activity.getStartTime(), activity.getEndTime(), giftIdList);
		Long targetSumValue = activityRecordMapper.getTargetLoveNum(userId, activity.getStartTime(), activity.getEndTime(), giftIdList);

		int targetValue = 999999999;
		int flag = 0;
		JSONArray array = JSON.parseArray(activity.getProperty1());
		for (int i = 0; i < array.size(); i++) {
			JSONArray gifts = array.getJSONObject(i).getJSONArray("gifts");
			for (int j = 0; j < gifts.size(); j++) {
				if(gifts.getJSONObject(j).getInteger("giftId").equals(giftId)){
					targetValue = gifts.getJSONObject(i).getInteger("targetValue");
					if(j == 1){
						flag = 1;
					}
					break;
				}
			}
		}

		if((flag == 0 ? sumValue : targetSumValue) < targetValue){
			throw new ServiceException("未达到领取值");
		}
		//领取
		receive(userId, giftId, sysDict);
		//返回
		Map<String, Object> result = new HashMap<>();
		result.put("giftName", sysDict.getName());
		result.put("giftUrl", sysDict.getProperty2());
		redisUtil.del(RedisConstans.ACTIVITY_LOVE_REWARD, loveDto.getUserId());
		return result;
	}

	/**
	 * 获取奖励礼物状态
	 * @param userId
	 * @return
	 */
	private int getSumValue(String userId){
		int sum = 0;
		List<Map<String,Object>> mapList = redisUtil.hGetValuesList(RedisConstans.ACTIVITY_GIFT_USER + userId);
		if (!CollectionUtils.isEmpty(mapList)) {
			for (Map<String, Object> map : mapList) {
				sum += (Integer) map.get("loveNum");
			}
		}
		return sum;
	}

	private boolean isReceiveRecord(String userId, Integer giftId){
		boolean result = false;
		QueryWrapper<ActivityRecord> wrapper = new QueryWrapper<>();
		wrapper.lambda().eq(ActivityRecord::getActivityId, 2).eq(ActivityRecord::getGiftId, giftId).eq(ActivityRecord::getType, 1);
		wrapper.last("limit 1");
		wrapper.lambda().eq(ActivityRecord::getUserId, userId);
		ActivityRecord activityRecord = activityRecordMapper.selectOne(wrapper);
		if(activityRecord != null){
			result = true;
		}
		return result;
	}

	/**
	 * 领取并保存礼物和记录
	 * @param userId
	 * @param giftId
	 * @return
	 */
	public void receive(String userId, Integer giftId, SysDict sysDict){
		// 保存装扮礼物数据
		LocalDateTime nowDateTime = LocalDateTime.now();
		UserDressUp dressUp = new UserDressUp();
		dressUp.setUserId(userId);
		dressUp.setType(Integer.valueOf(sysDict.getProperty1()));
		dressUp.setDressId(sysDict.getId());
		dressUp.setPrice(Integer.valueOf(sysDict.getProperty5()));
		dressUp.setStatus(0);
		dressUp.setDuration(StringUtils.isBlank(sysDict.getProperty4()) ? 0 : Integer.valueOf(sysDict.getProperty4()));
		dressUp.setLimitedType(Integer.valueOf(sysDict.getProperty7()));
		dressUp.setCreateTime(nowDateTime);
		dressUp.setUpdateTime(nowDateTime);
		userDressUpMapper.insert(dressUp);
		//保存赠送记录到用户账本表
		UserAccountBook accountBook = new UserAccountBook();
		accountBook.setCurrencyType(6);
		accountBook.setOrderId(String.valueOf(dressUp.getDressId()));
		accountBook.setAccountTitle("双11活动领取");
		accountBook.setReceivingAccount(userId);
		accountBook.setReceivingAmount(0);
		accountBook.setPaymentAccountTotal(0);
		accountBook.setPaymentAccountBalance(0);
		accountBook.setPaymentAmount(0);
		accountBook.setNote("双11活动奖品");
		userAccountBookMapper.insert(accountBook);
		//插入领取记录表
		ActivityRecord record = new ActivityRecord();
		record.setActivityId(2);
		record.setType(1);
		record.setUserId(userId);
		record.setGiftId(giftId);
		activityRecordMapper.insert(record);
	}

	private boolean checkSensitive(String content) {
		Map<String, Object> params = new HashMap<>();
		params.put("content", content);
		params.put("timestamp", System.currentTimeMillis()/1000);
		String requestBody = JSON.toJSONString(params);
		HttpRequest request = HttpRequest.post(host + "/rest/content_check/sensitive").header("sign", SignUtils
				.sign(params)).body(requestBody);
		String response = request.execute().body();
		log.info("methodName:checkSensitive,response={}",response);
		Result result = JSON.parseObject(response, Result.class);
		if(result.getCode() != 0){
			throw new ServiceException(result.getMsg());
		}
		Boolean isSensitive = (Boolean) result.getFromData("isSensitive");
		if(isSensitive){
			return true;
		}
		return false;
	}
}
